<script>
  import { onMount, onDestroy } from 'svelte';
  import * as echarts from 'echarts';
  import { useChartData } from '../utils/useChartData.js';

  // ===========================
  // Props (exported)
  // ===========================

  /** API endpoint for fetching data */
  export let endpoint = '';

  /** Chart title */
  export let title = '';

  /** Y-axis unit name */
  export let unit = '';

  /** Polling interval in milliseconds (0 = no polling) */
  export let polling = 0;

  /** Authentication token */
  export let authToken = '';

  /** Static data (alternative to endpoint) */
  export let data = null;

  /** Chart height in pixels */
  export let height = 400;

  // ===========================
  // Internal State
  // ===========================

  let chartContainer;
  let chartInstance = null;

  // Use shared data fetching logic
  const { loading, error, fetchData, cleanup } = useChartData();

  // ===========================
  // Chart Rendering
  // ===========================

  function renderChart(chartData) {
    if (!chartInstance || !chartContainer) return;

    // Parse data format
    // Expected format:
    // {
    //   title: string,
    //   categories: string[],  // X-axis labels
    //   boxplotData: [[min, Q1, median, Q3, max], ...],
    //   outliers: [[categoryIndex, value], ...]
    // }
    // OR
    // {
    //   xAxis: { data: [...] },
    //   series: [...]
    // }

    let categories = [];
    let boxplotData = [];
    let outliers = [];
    let chartTitle = title || chartData.title || '';
    let yAxisName = unit || chartData.unit || 'Value';

    // Handle different data formats
    if (chartData.categories && chartData.boxplotData) {
      categories = chartData.categories;
      boxplotData = chartData.boxplotData;
      outliers = chartData.outliers || [];
    } else if (chartData.xAxis && chartData.series) {
      categories = chartData.xAxis.data || chartData.xAxis.categories || [];

      // Find boxplot series
      const boxplotSeries = chartData.series.find(s => s.type === 'boxplot');
      if (boxplotSeries) {
        boxplotData = boxplotSeries.data || [];
      }

      // Find scatter series (outliers)
      const scatterSeries = chartData.series.find(s => s.type === 'scatter');
      if (scatterSeries) {
        outliers = scatterSeries.data || [];
      }
    }

    const option = {
      title: {
        text: chartTitle,
        left: 'center',
        textStyle: {
          fontSize: 16,
          fontWeight: '600',
          color: '#374151',
        },
      },
      tooltip: {
        trigger: 'item',
        axisPointer: {
          type: 'shadow',
        },
        formatter: function (param) {
          if (param.seriesType === 'boxplot') {
            const value = param.value;
            return [
              `<strong>${param.name}</strong><br/>`,
              `Upper: ${value[5]}<br/>`,
              `Q3: ${value[4]}<br/>`,
              `Median: ${value[3]}<br/>`,
              `Q1: ${value[2]}<br/>`,
              `Lower: ${value[1]}`,
            ].join('');
          } else if (param.seriesType === 'scatter') {
            return `<strong>Outlier</strong><br/>Category: ${categories[param.value[0]]}<br/>Value: ${param.value[1]}`;
          }
          return param.name;
        },
      },
      grid: {
        left: '10%',
        right: '10%',
        bottom: '15%',
        top: title ? '15%' : '10%',
        containLabel: true,
      },
      xAxis: {
        type: 'category',
        data: categories,
        boundaryGap: true,
        nameGap: 30,
        splitArea: {
          show: false,
        },
        splitLine: {
          show: false,
        },
        axisLabel: {
          rotate: categories.length > 5 ? 30 : 0,
          color: '#6b7280',
        },
        axisLine: {
          lineStyle: {
            color: '#e5e7eb',
          },
        },
      },
      yAxis: {
        type: 'value',
        name: yAxisName,
        nameTextStyle: {
          color: '#6b7280',
          fontSize: 12,
        },
        splitArea: {
          show: true,
          areaStyle: {
            color: ['rgba(250,250,250,0.3)', 'rgba(245,245,245,0.3)'],
          },
        },
        axisLabel: {
          color: '#6b7280',
        },
        axisLine: {
          lineStyle: {
            color: '#e5e7eb',
          },
        },
        splitLine: {
          lineStyle: {
            color: '#e5e7eb',
          },
        },
      },
      series: [
        {
          name: 'Boxplot',
          type: 'boxplot',
          data: boxplotData,
          itemStyle: {
            color: '#60a5fa',
            borderColor: '#3b82f6',
            borderWidth: 2,
          },
          emphasis: {
            itemStyle: {
              color: '#3b82f6',
              borderColor: '#2563eb',
              borderWidth: 2,
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              shadowColor: 'rgba(59, 130, 246, 0.5)',
            },
          },
        },
        {
          name: 'Outliers',
          type: 'scatter',
          data: outliers,
          symbolSize: 8,
          itemStyle: {
            color: '#ef4444',
            borderColor: '#dc2626',
            borderWidth: 1,
          },
          emphasis: {
            itemStyle: {
              color: '#dc2626',
              borderColor: '#b91c1c',
              borderWidth: 2,
              shadowBlur: 10,
              shadowColor: 'rgba(239, 68, 68, 0.5)',
            },
          },
          tooltip: {
            formatter: function (param) {
              return `<strong>Outlier</strong><br/>Category: ${categories[param.value[0]]}<br/>Value: ${param.value[1]}`;
            },
          },
        },
      ],
    };

    chartInstance.setOption(option, true);
  }

  // ===========================
  // Lifecycle
  // ===========================

  function handleResize() {
    chartInstance?.resize();
  }

  onMount(() => {
    if (chartContainer) {
      chartInstance = echarts.init(chartContainer);

      // Render provided data immediately
      if (data) {
        renderChart(data);
        loading.set(false);
      }
      // Otherwise fetch from endpoint
      else if (endpoint) {
        fetchData(endpoint, authToken, polling, renderChart);
      }

      window.addEventListener('resize', handleResize);
    }
  });

  onDestroy(() => {
    cleanup();
    window.removeEventListener('resize', handleResize);
    if (chartInstance) {
      chartInstance.dispose();
      chartInstance = null;
    }
  });
</script>

<div class="boxplot-chart">
  <div
    class="chart-container"
    bind:this={chartContainer}
    style="height: {height}px;"
  ></div>

  {#if $loading}
    <div class="chart-loading">
      <div class="spinner"></div>
      <p>Loading data...</p>
    </div>
  {/if}

  {#if $error}
    <div class="chart-error">
      <p>Error: {$error}</p>
    </div>
  {/if}
</div>

<style>
  .boxplot-chart {
    position: relative;
    width: 100%;
    background: white;
    border-radius: 8px;
    padding: 1rem;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  }

  .chart-container {
    width: 100%;
  }

  .chart-loading,
  .chart-error {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    z-index: 10;
  }

  .chart-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
  }

  .spinner {
    width: 40px;
    height: 40px;
    border: 4px solid #e5e7eb;
    border-top-color: #3b82f6;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
  }

  @keyframes spin {
    to {
      transform: rotate(360deg);
    }
  }

  .chart-loading p,
  .chart-error p {
    color: #6b7280;
    font-size: 0.875rem;
  }

  .chart-error button {
    margin-top: 0.5rem;
    padding: 0.5rem 1rem;
    background: #3b82f6;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.875rem;
  }

  .chart-error button:hover {
    background: #2563eb;
  }

  @media (max-width: 768px) {
    .boxplot-chart {
      padding: 0.5rem;
    }
  }
</style>
